package ws.jdbc.concurrent.driver.sqlserver.tds.datatypes;

import java.nio.ByteBuffer;

/**
 * Fixed-length data type.
 *
 * <p>
 * <a href="http://msdn.microsoft.com/en-us/library/dd341171">Reference</a>
 * </p>
 *
 * @author Wilson Santos, 36228 <wilson.santos@ua.pt>
 */
public class FIXEDLENTYPE {

  /** Null (no data associated with this type). */
  public static final byte NULLTYPE = 0x1F;
  /** TinyInt (1 byte data representation).*/
  public static final byte INT1TYPE = 0x30;
  /** Bit (1 byte data representation).*/
  public static final byte BITTYPE = 0x32;
  /** SmallInt (2 byte data representation).*/
  public static final byte INT2TYPE = 0x34;
  /** Int (4 byte data representation).*/
  public static final byte INT4TYPE = 0x38;
  /** SmallDateTime (4 byte data representation).*/
  public static final byte DATETIM4TYPE = 0x3A;
  /** Real (4 byte data representation).*/
  public static final byte FLT4TYPE = 0x3B;
  /** Money (8 byte data representation).*/
  public static final byte MONEYTYPE = 0x3C;
  /** DateTime (8 byte data representation).*/
  public static final byte DATETIMETYPE = 0x3D;
  /** Float (8 byte data representation).*/
  public static final byte FLT8TYPE = 0x3E;
  /** SmallMoney (4 byte data representation).*/
  public static final byte MONEY4TYPE = 0x7A;
  /** BigInt (8 byte data representation).*/
  public static final byte INT8TYPE = 0x7F;

  /**
   * Check if a given byte represents a FIXEDLENTYPE data type.
   *
   * @param type byte to check.
   *
   * @return {@code true} if {@code type} is a FIXEDLENTYPE data type.
   */
  public static boolean isFixedLenType(final byte type) {
    return (type == NULLTYPE) || (type == INT1TYPE) || (type == BITTYPE)
            || (type == INT2TYPE) || (type == INT4TYPE) || (type == DATETIM4TYPE)
            || (type == FLT4TYPE) || (type == MONEYTYPE) || (type == DATETIMETYPE)
            || (type == FLT8TYPE) || (type == MONEY4TYPE) || (type == INT8TYPE);
  }

  /**
   * Read a fixed-length type from the input stream.
   *
   * @param stream input stream to read the type from.
   * @param type fixed-length type.
   *
   * @return array with the bytes of the fixed-length type.
   */
  public static byte[] read(final ByteBuffer stream, final byte type) {
    byte[] ret;

    switch (type) {
      // 0-byte
      case NULLTYPE:
        ret = new byte[0];
      case INT1TYPE:
      case BITTYPE:
        ret = new byte[1];
      // 2-byte
      case INT2TYPE:
        ret = new byte[2];
      // 4-byte
      case INT4TYPE:
      case DATETIM4TYPE:
      case FLT4TYPE:
      case MONEY4TYPE:
        ret = new byte[4];
        break;
      // 8-byte
      case MONEYTYPE:
      case DATETIMETYPE:
      case FLT8TYPE:
      case INT8TYPE:
        ret = new byte[8];
        break;
      default:
        ret = null;
        throw new IllegalArgumentException("Unknown fixed-length data type: 0x" + Integer.toHexString(0x0FF & type));
    }
    stream.get(ret);
    return ret;
  }
}
